#include <string.h>
#include <iostream>
#include <fstream>
#include <vector>

#include <opencv2/opencv.hpp>

#include "ROIExtracter.h"
#include "palmdll.h"
#include "Dataset/IITDDatabase.h"
#include "Dataset/IITDTestset.h"
#include "Dataset/TongjiDatabase.h"
#include "Dataset/TongjiTestset.h"
#include "ValidatorWithSave.h"
#include "ValidatorWithROI.h"
#include "Saver.h"

using namespace std;

Validator *get_single_validator_from_factory(Database &db, string fincon_save_file_path, string roi_save_file_path, string roi_load_file_path)
{
    static Validator *vd = new ValidatorWithSave(db, fincon_save_file_path, roi_save_file_path);
    //static Validator *vd = new ValidatorWithROI(db, roi_load_file_path);
    return vd;
}

mAP *generate_EER(Database &db, Testset &test_set, Validator *vd)
{
    float score = 0;
    int count = 0;
    Testset::iterator i_end = test_set.end();

    for (float TH = 0.35; TH < 0.475; TH += 0.025)
    {
        //fnr
        int count = 0;
        float far = 0;
        for (Testset::iterator i = test_set.begin(); i != i_end; ++i)
        {
            far += 1 - vd->validate(*i, i->person_id, TH);
            count++;
        }
        cout << "FAR under TH=" << TH << "  is :" << far / count << endl;

        //far
        count = 0;
        float ffr = 0;
        for (Testset::iterator i = test_set.begin(); i != i_end; ++i)
        {
            // int current_person = i->person_id;
            // i->person_id = db.next_person(i->person_id);
            // for (; i->person_id != current_person; i->person_id = db.next_person(i->person_id))
            // {
            //     ffr += vd->validate(*i, TH);
            //     count++;
            // }
            for (int j = 0; j < 3; j++)
            {
                ffr += vd->validate(*i, db.next_radom_person(i->person_id), TH);
                count++;
            }
        }
        cout << "FFR under TH=" << TH << "  is :" << ffr / count << endl;
    }

    return NULL;
}

void generate_rank1(Database &db, Testset &test_set, Validator *vd)
{
    const float TH = 0.4;
    float count = 0, correct = 0;
    Testset::iterator i_end = test_set.end();
    for (Testset::iterator i = test_set.begin(); i != i_end; ++i)
    {
        int person_id = vd->identify(*i, TH);
        correct += person_id == i->person_id ? 1 : 0;
        count++;
        cout << "rank-1 recognize rate=" << correct / count << endl;
    }
}

int main(int argc, char const *argv[])
{
    //pwd == argv[0]
    const string database_dir_path(argv[1]);
    const string testset_dir_path(argv[2]);
    const string fincon_save_file_path(argv[3]);
    const string roi_save_file_path(argv[4]);
    const string mAP_save_file_path(argv[5]);
    const string roi_load_file_path(argv[6]);

    TongjiDatabase db(database_dir_path);
    db.load();
    TongjiTestset test_set(testset_dir_path);
    test_set.load();
    Saver<mAP> s_mAP;
    Validator *vd = get_single_validator_from_factory(db, fincon_save_file_path, roi_save_file_path, roi_load_file_path);

    // generate_EER(db, test_set, vd);
    generate_rank1(db, test_set, vd);
    //delete vd;

    return 0;
}
